import java.util.*;

import org.jfree.ui.RefineryUtilities;

public class App {

	public static final int TRIES = 50;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		if (args.length < 2) {
			System.err.println("Usage: App <NumColors>");
			System.exit(1);
		}
		
		int numColors = Integer.parseInt(args[0]);
		String mapFile = args[1];
		
		// get input
		InputData input= new InputData(mapFile);
		
		int length = input.getMaxNumber(); // get how many vertices in input
		boolean solutionFound = false;
		int maxError = input.getMaxError();
		List<List<Double>> retLists = null;
		List<List<Double>> bestRetLists = null;
		Chromosome best = null;
		Chromosome currBest = null;
		int bestRun=0;			
		
		for (int i = 0; i < TRIES && !solutionFound; ++i) {
			
			System.out.println("Current try: " + i);

			
			// check if there's a need to decrease PENALTY factor
			if (numColors == 3)
				if (i < TRIES * 0.2)
					GeneticUtils.PENALTY = 5;
				else if (i < TRIES * 0.3)
					GeneticUtils.PENALTY = 3;
				else if (i < TRIES * 0.4)
					GeneticUtils.PENALTY = 2.2;
				else if (i < TRIES * 0.6)
					GeneticUtils.PENALTY = 1.6;
				else 
					GeneticUtils.PENALTY = 1.2;
					
			
			// run the genetic algorithm
			GeneticEngine engine = new GeneticEngine(length + 1, input, 4);
			retLists = engine.start();
			


			// get result from the genetic algorithm
			currBest = engine.getBest();
				
			if (i==0){
				best = currBest;
				bestRetLists = retLists;
			}
			else
				if (GeneticUtils.getErrors(currBest) < GeneticUtils.getErrors(best)){
					best=currBest;
					bestRetLists = retLists;
					bestRun=i;
				}
			if (best.getFitness() == maxError)
				solutionFound = true;
			
			System.out.println("try "+i);
			System.out.println("best try: "+bestRun);
			System.out.println("best fitness: "+best.getFitness());
			System.out.println("best penalty: "+best.get4Count() * GeneticUtils.PENALTY);
			System.out.println("best total fitness: "+ (best.getFitness()+best.get4Count() * GeneticUtils.PENALTY));
			System.out.println("best errors: "+GeneticUtils.getErrors(best)); 
			System.out.println("******************************");
		}
		
		List<Integer> data = best.getRange(length+1);
		
		XYChart chart = new XYChart("Fitness vs. Generations", bestRetLists.get(0), bestRetLists.get(1));
		chart.pack();
//        RefineryUtilities.centerFrameOnScreen(chart);
        chart.setLocation(0,0);
        chart.setVisible(true);
		
		// visualization of result
		input.showColordTable(data, chart);
		
		

	}

}